home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 726-750 / 741 / rkrm_lib1 / rkrm_lib1.lha / Intuition / Boopsi / RKMModel.c < prev    next >
C/C++ Source or Header  |  1992-09-03  |  14KB  |  233 lines

  1. ;/* RKMModel.c - A simple custom modelclass subclass.
  2. LC -cfist -b1 -y -v -j73 rkmmodel.c
  3. quit ;*/
  4.  
  5. /*
  6. Copyright (c) 1992 Commodore-Amiga, Inc.
  7.  
  8. This example is provided in electronic form by Commodore-Amiga, Inc. for
  9. use with the "Amiga ROM Kernel Reference Manual: Libraries", 3rd Edition,
  10. published by Addison-Wesley (ISBN 0-201-56774-1).
  11.  
  12. The "Amiga ROM Kernel Reference Manual: Libraries" contains additional
  13. information on the correct usage of the techniques and operating system
  14. functions presented in these examples.  The source and executable code
  15. of these examples may only be distributed in free electronic form, via
  16. bulletin board or as part of a fully non-commercial and freely
  17. redistributable diskette.  Both the source and executable code (including
  18. comments) must be included, without modification, in any copy.  This
  19. example may not be published in printed form or distributed with any
  20. commercial product.  However, the programming techniques and support
  21. routines set forth in these examples may be used in the development
  22. of original executable software products for Commodore Amiga computers.
  23.  
  24. All other rights reserved.
  25.  
  26. This example is provided "as-is" and is subject to change; no
  27. warranties are made.  All use is at your own risk. No liability or
  28. responsibility is assumed.
  29. */
  30.  
  31. #include <exec/types.h>
  32. #include <intuition/intuition.h>
  33. #include <intuition/classes.h>
  34. #include <intuition/classusr.h>
  35. #include <intuition/imageclass.h>
  36. #include <intuition/gadgetclass.h>
  37. #include <intuition/cghooks.h>
  38. #include <intuition/icclass.h>
  39. #include <utility/tagitem.h>
  40. #include <utility/hooks.h>
  41. #include <clib/intuition_protos.h>
  42. #include <clib/utility_protos.h>
  43. #include <clib/alib_protos.h>
  44. #include <clib/alib_stdio_protos.h>
  45.  
  46. extern struct Library *IntuitionBase, *UtilityBase;
  47.  
  48. /*************************************************************************************************/
  49. /****************  The attributes defined by this class  *****************************************/
  50. /*************************************************************************************************/
  51. #define RKMMOD_CurrVal  (TAG_USER + 1) /* This attribute is the current value of the model.*******/
  52.                                        /**********************************************************/
  53. #define RKMMOD_Up       (TAG_USER + 2) /* These two are fake attributes that rkmmodelclass *******/
  54. #define RKMMOD_Down     (TAG_USER + 3) /* uses as pulse values to increment/decrement the  *******/
  55.                                        /* rkmmodel's RKMMOD_CurrVal attribute.             *******/
  56.                                        /**********************************************************/
  57. #define RKMMOD_Limit    (TAG_USER + 4) /* This attribute contains the upper bound of the   *******/
  58.                                        /* rkmmodel's RKMMOD_CurrVal.  The rkmmodel has a   *******/
  59.                                        /* static lower bound of zero.                      *******/
  60. /*************************************************************************************************/
  61.  
  62. #define DEFAULTVALLIMIT 100L /* If the programmer doesn't set               */
  63.                              /* RKMMOD_Limit, it defaults to this.          */
  64. struct RKMModData {
  65.     ULONG currval;       /* The instance data for this class.               */
  66.     ULONG vallimit;
  67. };
  68.  
  69. /*************************************************************************************************/
  70. /**************************      The functions in this module     ********************************/
  71. /*************************************************************************************************/
  72. void    geta4(void);                                                              /***************/
  73. Class  *initRKMModClass(void);                                                    /***************/
  74. BOOL    freeRKMModClass(Class *);                                                 /***************/
  75. ULONG   dispatchRKMModel(Class *, Object *, Msg);                                 /***************/
  76. void    NotifyCurrVal(Class *, Object *, struct opUpdate *, struct RKMModData *); /***************/
  77. /*************************************************************************************************/
  78.  
  79. /*************************************************************************************************/
  80. /********************************   Initialize the class    **************************************/
  81. /*************************************************************************************************/
  82. Class   *initRKMModClass(void)                /* Make the class and set     */
  83. {                                             /* up the dispatcher's hook.  */
  84.     Class *cl;
  85.     extern ULONG HookEntry();  /*      <-------   defined in amiga.lib.     */
  86.  
  87.     if ( cl =  MakeClass( NULL,
  88.                 "modelclass", NULL,
  89.                 sizeof ( struct RKMModData ),
  90.                 0 ))
  91.     {
  92.         cl->cl_Dispatcher.h_Entry = HookEntry;           /* initialize the  */
  93.         cl->cl_Dispatcher.h_SubEntry = dispatchRKMModel; /* cl_Dispatcher   */
  94.                                                          /* Hook.           */
  95.     }
  96.     return ( cl );
  97. }
  98.  
  99. /*************************************************************************************************/
  100. /*********************************      Free the class     ***************************************/
  101. /*************************************************************************************************/
  102. BOOL freeRKMModClass( Class *cl )
  103. {
  104.     return (FreeClass(cl));
  105. }
  106.  
  107. /*************************************************************************************************/
  108. /********************************     The class Dispatcher     ***********************************/
  109. /*************************************************************************************************/
  110. ULONG dispatchRKMModel(Class *cl, Object *o, Msg msg)
  111. {
  112.     struct RKMModData *mmd;
  113.     APTR retval = NULL;  /* A generic return value used by this class's methods.  The            */
  114.                          /* meaning of this field depends on the method.  For example,           */
  115.                          /* OM_GET uses this a a boolean return value, while OM_NEW              */
  116.                          /* uses it as a pointer to the new object.                              */
  117.     geta4();    /* SAS/C and Manx function - makes sure A4 contains global data pointer.         */
  118.  
  119.     switch (msg->MethodID)
  120.     {
  121.         case OM_NEW:     /* Pass message onto superclass first so it can set aside the memory    */
  122.                          /* for the object and take care of superclass instance data.            */
  123.             if (retval = (APTR)DoSuperMethodA(cl, o, msg))
  124.             {            /************************************************************************/
  125.                          /* For the OM_NEW method, the object pointer passed to the dispatcher   */
  126.                          /* does not point to an object (how could it? The object doesn't exist  */
  127.                          /* yet.)  DoSuperMethodA() returns a pointer to a newly created         */
  128.                          /* object. INST_DATA() is a macro defined in <intuition/classes.h>      */
  129.                          /* that returns a pointer to the object's instance data that is local   */
  130.                          /* to this class. For example, the instance data local to this class    */
  131.                          /* is the RKMModData structure defined above.                           */
  132.                          /************************************************************************/
  133.                 mmd = INST_DATA(cl, retval);
  134.                 mmd->currval = GetTagData(RKMMOD_CurrVal, 0L, /* initialize object's attributes. */
  135.                                           ((struct opSet *)msg)->ops_AttrList);
  136.                 mmd->vallimit = GetTagData(RKMMOD_Limit, DEFAULTVALLIMIT,
  137.                                            ((struct opSet *)msg)->ops_AttrList);
  138.             }
  139.             break;
  140.         case OM_SET:
  141.         case OM_UPDATE:
  142.             mmd = INST_DATA(cl, o);
  143.             DoSuperMethodA(cl, o, msg);   /* Let the superclasses set their attributes first.    */
  144.             {
  145.                 struct TagItem *tstate, *ti;    /* grab some temp variables off of the stack.    */
  146.  
  147.                 ti = ((struct opSet *)msg)->ops_AttrList;
  148.                 tstate = ti;
  149.  
  150.                         /* Step through all of the attribute/value pairs in the list.  Use the   */
  151.                         /* utility.library tag functions to do this so they can properly process */
  152.                         /* special tag IDs like TAG_SKIP, TAG_IGNORE, etc.                       */
  153.  
  154.                 while (ti = NextTagItem(&tstate))    /* Step through all of the attribute/value  */
  155.                 {                 /* pairs in the list. Use the utility.library tag functions    */
  156.                                   /* to do this so they can properly process special tag IDs     */
  157.                                   /* like TAG_SKIP, TAG_IGNORE, etc.                             */
  158.                     switch (ti->ti_Tag)
  159.                     {
  160.                         case RKMMOD_CurrVal:
  161.                             if ((ti->ti_Data) > mmd->vallimit) ti->ti_Data =
  162.                                     mmd->vallimit;
  163.                             mmd->currval = ti->ti_Data;
  164.                             NotifyCurrVal(cl, o, msg, mmd);
  165.                             retval = (APTR)1L;  /* Changing RKMMOD_CurrVal can cause a visual    */
  166.                             break;              /* change to gadgets in the rkmmodel's broadcast */
  167.                                                 /* list.  The rkmmodel has to tell the applica-  */
  168.                                                 /* tion by returning a value besides zero.       */
  169.                         case RKMMOD_Up:
  170.                             mmd->currval++;
  171.  
  172.                                  /* Make sure the current value is not greater than value limit. */
  173.                             if ((mmd->currval) > mmd->vallimit) mmd->currval = mmd->vallimit;
  174.                             NotifyCurrVal(cl, o, msg, mmd);
  175.                             retval = (APTR)1L;  /* Changing RKMMOD_Up can cause a visual         */
  176.                             break;              /* change to gadgets in the rkmmodel's broadcast */
  177.                                                 /* list.  The rkmmodel has to tell the applica-  */
  178.                                                 /* tion by returning a value besides zero.       */
  179.                         case RKMMOD_Down:
  180.                             mmd->currval--;
  181.                                     /* Make sure currval didn't go negative. */
  182.                             if ((LONG)(mmd->currval) == -1L)
  183.                                 mmd->currval = 0L;
  184.                             NotifyCurrVal(cl, o, msg, mmd);
  185.                             retval = (APTR)1L;  /* Changing RKMMOD_Down can cause a visual       */
  186.                             break;              /* change to gadgets in the rkmmodel's broadcast */
  187.                                                 /* list.  The rkmmodel has to tell the applica-  */
  188.                                                 /* tion by returning a value besides zero.       */
  189.                         case RKMMOD_Limit:
  190.                             mmd->vallimit = ti->ti_Data; /* Set the limit.  Note that this does  */
  191.                             break;                       /* not do bounds checking on the        */
  192.                                                          /* current RKMModData.currval value.    */
  193.                     }
  194.                 }
  195.             }
  196.             break;
  197.         case OM_GET:                     /* The only attribute that is "gettable" in this        */
  198.             mmd = INST_DATA(cl, o);      /* class or its superclasses is RKMMOD_CurrVal.         */
  199.             if ((((struct opGet *)msg)->opg_AttrID) == RKMMOD_CurrVal)
  200.             {
  201.                 *(((struct opGet *)msg)->opg_Storage) = mmd->currval;
  202.                 retval = (Object *)TRUE;
  203.             }
  204.             else retval = (APTR)DoSuperMethodA(cl, o, msg);
  205.             break;
  206.         default:       /* rkmmodelclass does not recognize the methodID, so let the superclass's */
  207.                        /* dispatcher take a look at it.                                          */
  208.             retval = (APTR)DoSuperMethodA(cl, o, msg);
  209.             break;
  210.     }
  211.     return((ULONG)retval);
  212. }
  213.  
  214.  
  215.  
  216. void NotifyCurrVal(Class *cl, Object *o, struct opUpdate *msg, struct RKMModData *mmd)
  217. {
  218.     struct TagItem tt[2];
  219.  
  220.     tt[0].ti_Tag = RKMMOD_CurrVal; /* make a tag list.  */
  221.     tt[0].ti_Data = mmd->currval;
  222.     tt[1].ti_Tag = TAG_DONE;
  223.                                 /* If the RKMMOD_CurrVal changes, we want everyone to know about */
  224.     DoSuperMethod(cl, o,        /* it. Theoretically, the class is supposed to send itself a     */
  225.              OM_NOTIFY,         /* OM_NOTIFY message. Because this class lets its superclass     */
  226.              tt,                /* handle the OM_NOTIFY message, it skips the middleman and      */
  227.              msg->opu_GInfo,    /* sends the OM_NOTIFY directly to its superclass.               */
  228.  
  229.              ((msg->MethodID == OM_UPDATE) ? (msg->opu_Flags) : 0L)); /* If this is an OM_UPDATE */
  230.                                 /* method, make sure the part the OM_UPDATE message adds to the  */
  231.                                 /* OM_SET message gets added.  That lets the dispatcher handle   */
  232. }                               /* OM_UPDATE and OM_SET in the same case.                        */
  233.